資料視覺化¶

Python 資料視覺化工具簡介

數據交點 | 郭耀仁 https://linktr.ee/yaojenkuo

In [1]:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import folium
import plotly.express as px

關於資料科學的應用場景¶

什麼是資料科學¶

資料科學是一門將資料(Data)提煉為資訊(Information)的學科,提煉過程中可能包含資料載入、資料操作、探索性分析以及監督式學習等。

(複習)視覺化被用於探索與溝通兩個場景¶

Imgur

來源:R for Data Science

(複習)載入、清理與轉換外型合稱為 "Wrangle"¶

Source: R for Data Science

什麼是資料科學的應用場景¶

  • Import 資料的載入。
  • Tidy 資料清理。
  • Transform 資料外型與類別的轉換。
  • Visualise 探索性分析。
  • Model 分析與預測模型。
  • Communicate 溝通分享。

Python 的資料視覺化工具¶

  • "Wrangle":Pandas
  • 探索性分析與溝通分享:
    • 靜態:Matplotlib、Seaborn
    • 地理資訊:Folium
    • 動態:Plotly
    • 網頁應用程式:Dash、Streamlit

資料的載入、清理與轉換¶

常見的來源資料格式¶

  1. 純文字檔案。
  2. 試算表。
  3. 關聯式資料庫中的資料表。

什麼是純文字檔案¶

只有文字所構成的電腦檔案,不包含字型的樣式或者段落標記,能夠使用最簡單的文字編輯器(例如 Windows 的「記事本」、macOS 的 TextEdit)直接開啟檢視。

特定符號分隔的純文字檔案¶

  • 透過特定符號分隔欄位的結構化資料。
  • 常見的有逗號(,)、分號(;)、Tab 鍵(\t)等。
  • 最廣泛使用的是逗號,因此有特定的副檔名 .csv 意指逗號分隔值(Comma-separated values)。

使用 pd.read_csv() 函數載入純文字檔案¶

  • 要先以 import pandas as pd 載入 Pandas
  • 以 df.head() 檢視前五列。
In [2]:
data_url = "https://raw.githubusercontent.com/datainpoint/classroom-data-visualization/main/data/daily_report.csv"
daily_report = pd.read_csv(data_url)
daily_report.head() # show the first 5 rows
Out[2]:
Combined_Key Last_Update Confirmed Deaths
0 Afghanistan 2022-04-21 04:20:46 178574 7680
1 Albania 2022-04-21 04:20:46 274606 3496
2 Algeria 2022-04-21 04:20:46 265746 6874
3 Andorra 2022-04-21 04:20:46 41013 153
4 Angola 2022-04-21 04:20:46 99287 1900
In [3]:
data_url = "https://raw.githubusercontent.com/datainpoint/classroom-data-visualization/main/data/lookup_table.csv"
lookup_table = pd.read_csv(data_url)
lookup_table.head() # show the first 5 rows
Out[3]:
UID Combined_Key iso2 iso3 Country_Region Province_State Admin2 Lat Long_ Population
0 4 Afghanistan AF AFG Afghanistan NaN NaN 33.93911 67.709953 38928341.0
1 8 Albania AL ALB Albania NaN NaN 41.15330 20.168300 2877800.0
2 10 Antarctica AQ ATA Antarctica NaN NaN -71.94990 23.347000 NaN
3 12 Algeria DZ DZA Algeria NaN NaN 28.03390 1.659600 43851043.0
4 20 Andorra AD AND Andorra NaN NaN 42.50630 1.521800 77265.0
In [4]:
data_url = "https://raw.githubusercontent.com/datainpoint/classroom-data-visualization/main/data/time_series.csv"
time_series = pd.read_csv(data_url)
time_series.head() # show the first 5 rows
Out[4]:
Date Country_Region Confirmed Deaths Daily_Cases Daily_Deaths
0 2020-01-22 Afghanistan 0 0 0 0
1 2020-01-22 Albania 0 0 0 0
2 2020-01-22 Algeria 0 0 0 0
3 2020-01-22 Andorra 0 0 0 0
4 2020-01-22 Angola 0 0 0 0

其他資料格式也可以使用 Pandas 的函數¶

  • 試算表:pd.read_excel()
  • 關聯式資料庫中的資料表:pd.read_sql()

來源:https://pandas.pydata.org/docs/user_guide/io.html

(複習)資料視覺化的前置作業¶

When it comes to making graphs, half the battle occurs before you call any graphing commands.

Winston Chang

常見的資料清理、轉換技巧都能夠使用 Pandas¶

  • 選擇欄位。
  • 篩選觀測值。
  • 排序。
  • 分組聚合。
  • 轉置。
  • 合併。
  • 連結。

資料視覺化 123¶

  1. 獲取資料。
  2. 將資料整理為合適的格式與類型。
  3. 輸入資料視覺化套件所定義好的函數。

試用 Python 的資料視覺化工具¶

In [5]:
country_list = ["US", "United Kingdom", "France", "Germany", "Canada", "Korea, South", "Japan", "Singapore", "Australia", "Taiwan", "New Zealand"]
daily_report_merge_lookup_table = pd.merge(daily_report, lookup_table, left_on="Combined_Key", right_on="Combined_Key")
filtered_daily_report_merge_lookup_table = daily_report_merge_lookup_table[daily_report_merge_lookup_table["Country_Region"].isin(country_list)]
data_for_bar = filtered_daily_report_merge_lookup_table.groupby('Country_Region')['Confirmed'].sum().sort_values(ascending=False)
data_for_bar
Out[5]:
Country_Region
US                80801162
France            28162002
Germany           23844536
United Kingdom    22060704
Korea, South      16674045
Japan              7484263
Australia          5563493
Canada             3669173
Singapore          1170970
New Zealand         865522
Taiwan               40186
Name: Confirmed, dtype: int64
In [6]:
data_for_line = time_series[time_series["Country_Region"].isin(country_list)].reset_index(drop=True)
data_for_line
Out[6]:
Date Country_Region Confirmed Deaths Daily_Cases Daily_Deaths
0 2020-01-22 Australia 0 0 0 0
1 2020-01-22 Canada 0 0 0 0
2 2020-01-22 France 0 0 0 0
3 2020-01-22 Germany 0 0 0 0
4 2020-01-22 Japan 2 0 2 0
... ... ... ... ... ... ...
9015 2022-04-20 New Zealand 865522 600 10574 18
9016 2022-04-20 Singapore 1170970 1319 3472 2
9017 2022-04-20 Taiwan 40186 856 2476 2
9018 2022-04-20 US 80801713 990208 68781 877
9019 2022-04-20 United Kingdom 22060704 173012 27321 514

9020 rows × 6 columns

In [7]:
confirmed_by_lat_long = daily_report_merge_lookup_table.groupby(['Combined_Key', 'Country_Region', "Province_State", "Admin2", "Lat", "Long_"])['Confirmed'].sum()
data_for_geo = pd.DataFrame(confirmed_by_lat_long).reset_index()
data_for_geo
Out[7]:
Combined_Key Country_Region Province_State Admin2 Lat Long_ Confirmed
0 Abbeville, South Carolina, US US South Carolina Abbeville 34.223334 -82.461707 6644
1 Acadia, Louisiana, US US Louisiana Acadia 30.295065 -92.414197 15039
2 Accomack, Virginia, US US Virginia Accomack 37.767072 -75.632346 6957
3 Ada, Idaho, US US Idaho Ada 43.452658 -116.241552 134084
4 Adair, Iowa, US US Iowa Adair 41.330756 -94.471059 1583
... ... ... ... ... ... ... ...
3199 Yuma, Arizona, US US Arizona Yuma 32.768957 -113.906667 62659
3200 Yuma, Colorado, US US Colorado Yuma 40.003468 -102.425867 1883
3201 Zapata, Texas, US US Texas Zapata 27.001564 -99.169872 3683
3202 Zavala, Texas, US US Texas Zavala 28.866172 -99.760508 4049
3203 Ziebach, South Dakota, US US South Dakota Ziebach 44.978819 -101.665462 663

3204 rows × 7 columns

Matplotlib¶

  1. 將資料整理為合適的格式與類型。
  2. 以 import matplotlib.pyplot as plt 載入。
  3. 建立「畫布物件」與「軸物件」。
  4. 使用「軸物件」的作圖方法建立主要圖形。
  5. 使用「軸物件」的作圖方法添加圖形元素。
  6. 顯示圖形。
In [8]:
# Plotting with Matplotlib
fig, ax = plt.subplots()
ax.barh(data_for_bar.sort_values().index, data_for_bar.sort_values().values)
ax.set_title("Confirmed By Country")
ax.set_xlabel("Number of Confirmed")
plt.show()

Seaborn¶

  1. 將資料整理為合適的格式與類型。
  2. 以 import seaborn as sns 載入。
  3. 使用 Seaborn 的作圖函數建立主要圖形。
  4. 調整作圖函數的參數添加圖形元素。
In [9]:
# Plotting with Seaborn
fig = sns.lineplot(x="Date", y="Confirmed", hue="Country_Region", data=data_for_line)
fig.set(xticks=[])
/var/folders/0b/r__z5mpn6ldgb_w2j7_y_ntr0000gn/T/ipykernel_55764/599519132.py:3: MatplotlibDeprecationWarning: Support for passing numbers through unit converters is deprecated since 3.5 and support will be removed two minor releases later; use Axis.convert_units instead.
  fig.set(xticks=[])
Out[9]:
[[]]

Folium¶

  1. 將資料整理為合適的格式與類型。
  2. 以 import folium 載入。
  3. 使用 Folium 的作圖函數建立主要圖形。
  4. 調整作圖函數的參數添加圖形元素。
In [10]:
# Plotting with Folium
url = "https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
state_geo = f"{url}/us-states.json"
m = folium.Map(location=[48, -102], zoom_start=3)
folium.Choropleth(
    geo_data=state_geo,
    name="choropleth",
    data=data_for_geo,
    columns=["Province_State", "Confirmed"],
    key_on="feature.properties.name",
    fill_color="YlGn",
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name="Confirmed",
).add_to(m)
folium.LayerControl().add_to(m)
Out[10]:
<folium.map.LayerControl at 0x7fe2c46f0610>
In [11]:
m
Out[11]:
Make this Notebook Trusted to load map: File -> Trust Notebook

Plotly¶

  1. 將資料整理為合適的格式與類型。
  2. 以 import plotly.express as px 載入。
  3. 使用 Plotly 的作圖函數建立主要圖形。
  4. 調整作圖函數的參數添加圖形元素。
In [12]:
# Plotting with Plotly
fig = px.bar(pd.DataFrame(data_for_bar).reset_index(), x="Confirmed", y="Country_Region", color="Country_Region")
fig.show()
In [13]:
# Plotting with Plotly
fig = px.line(data_for_line, x="Date", y="Confirmed",
              color="Country_Region", line_group="Country_Region", hover_name="Country_Region",
              line_shape="spline", render_mode="svg")
fig.show()
In [14]:
# Plotting with Plotly
fig = px.scatter_mapbox(data_for_geo, lat="Lat", lon="Long_", size="Confirmed", color="Confirmed",
                        size_max=50, mapbox_style="carto-positron", zoom=3, hover_name="Combined_Key")
fig.show()